<html>
<head>
<title>firstworks   Programming with Rudiments using the thread class</title>
<link href="../css/styles.css" rel="stylesheet">
</head>
<body>

<span class="heading">Using the thread class</span><br><br>

<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#ordinary">Ordinary Threads</a></li>
<li><a href="#detach">Detached Threads</a></li>
</ul>

<br>
<a name="intro"></a>
<h3>Introduction</h3>

<p>The <a href="../classes/html/classthread.html">thread class</a> provides a simple thread implementation.</p>

<p>In this implementation, each instance of the thread class corresponds to a separate thread.  When the spawn() method is called, a new thread is created, and the function is run in the new thread.  An argument may be passed to the function via the spawn() method.  This argument is usually used to pass a pointer to a class or struct, providing parameters for the thread function.</p>

<p>In these examples, two threads are spawned.  Each runs a separate instance of a "count" function which counts from 0 to some number and prints out the numbers.  Each thread is passed in a structure containing a pointer to the thread class, a thread id and a maximum number to count to.  The threads are not synchronized in any way, so the numbers will be printed out in seemingly random blocks.</p>

<p>Note that rudiments supports platforms that don't support threads, and it is possible to explicitly compile rudiments without thread support.  The supportsThreads() method returns true or false, indicating whether thread support is enabled or not.</p>

<br>
<a name="ordinary"></a>
<h3>Ordinary Threads</h3>

<p>Ordinarily, a thread runs until its function returns, or calls the exit() method.  Another thread (usually the main thread of the parent process) must call the wait() method to completely dispose of the thread (analagous to "waiting on a child process") and get its exit status.</p> 

<blockquote class="code">

<script type='text/javascript'>
<!--

-->
</script>
<font face="monospace">
<font color="#800080">#include&nbsp;</font><font color="#ff00ff">&lt;rudiments/thread.h&gt;</font><br>
<font color="#800080">#include&nbsp;</font><font color="#ff00ff">&lt;rudiments/process.h&gt;</font><br>
<font color="#800080">#include&nbsp;</font><font color="#ff00ff">&lt;rudiments/stdio.h&gt;</font><br>
<br>
<font color="#0000ff">// struct for passing arguments into the thread</font><br>
<font color="#2e8b57"><b>struct</b></font>&nbsp;args {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*th;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>int32_t</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>uint16_t</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max;<br>
};<br>
<br>
<font color="#0000ff">// function that will be spawned as a thread</font><br>
<font color="#2e8b57"><b>void</b></font>&nbsp;count(<font color="#2e8b57"><b>void</b></font>&nbsp;*args) {<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>struct</b></font>&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp; *a=(<font color="#2e8b57"><b>struct</b></font>&nbsp;args *)args;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a"><b>for</b></font>&nbsp;(<font color="#2e8b57"><b>uint16_t</b></font>&nbsp;c=<font color="#ff00ff">0</font>; c&lt;a-&gt;max; c++) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdoutput.printf(<font color="#ff00ff">&quot;&nbsp;&nbsp;</font><font color="#6a5acd">%d</font><font color="#ff00ff">:&nbsp;</font><font color="#6a5acd">%d</font><font color="#6a5acd">\n</font><font color="#ff00ff">&quot;</font>,a-&gt;id,c);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a-&gt;th-&gt;exit(&amp;(a-&gt;id));<br>
}<br>
<br>
<font color="#2e8b57"><b>int</b></font>&nbsp;main(<font color="#2e8b57"><b>int</b></font>&nbsp;argc,&nbsp;<font color="#2e8b57"><b>const</b></font>&nbsp;<font color="#2e8b57"><b>char</b></font>&nbsp;**argv) {<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// do we even support threads?</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a"><b>if</b></font>&nbsp;(!thread::supportsThreads()) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdoutput.printf(<font color="#ff00ff">&quot;thread are not supported</font><font color="#6a5acd">\n</font><font color="#ff00ff">&quot;</font>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process::exit(<font color="#ff00ff">1</font>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// create the threads</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;&nbsp;t1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;&nbsp;t2;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// define arguments to pass to each thread</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>struct</b></font>&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp; a1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a1.th=&amp;t1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a1.id=<font color="#ff00ff">1</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a1.max=<font color="#ff00ff">100</font>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>struct</b></font>&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp; a2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a2.th=&amp;t2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a2.id=<font color="#ff00ff">2</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a2.max=<font color="#ff00ff">200</font>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// spawn the threads</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.spawn((<font color="#2e8b57"><b>void</b></font>&nbsp;*(*)(<font color="#2e8b57"><b>void</b></font>&nbsp;*))count,(<font color="#2e8b57"><b>void</b></font>&nbsp;*)&amp;a1,<font color="#ff00ff">false</font>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2.spawn((<font color="#2e8b57"><b>void</b></font>&nbsp;*(*)(<font color="#2e8b57"><b>void</b></font>&nbsp;*))count,(<font color="#2e8b57"><b>void</b></font>&nbsp;*)&amp;a2,<font color="#ff00ff">false</font>);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// wait for the threads to exit</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>int32_t</b></font>&nbsp;t1status=-<font color="#ff00ff">1</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>int32_t</b></font>&nbsp;t2status=-<font color="#ff00ff">1</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.wait(&amp;t1status);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2.wait(&amp;t2status);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// print out the thread's exit status</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdoutput.printf(<font color="#ff00ff">&quot;t1 status:&nbsp;</font><font color="#6a5acd">%d</font><font color="#6a5acd">\n</font><font color="#ff00ff">&quot;</font>,t1status);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdoutput.printf(<font color="#ff00ff">&quot;t2 status:&nbsp;</font><font color="#6a5acd">%d</font><font color="#6a5acd">\n</font><font color="#ff00ff">&quot;</font>,t2status);<br>
}<br>
</font>
<!-- vim: set foldmethod=manual : -->
</blockquote>

<br>
<a name="detach"></a>
<h3>Detached Threads</h3>

<p>Alternatively, a thread may dissociate itself from the parent by calling the detach() method.  In this case, the thread is completely disposed of when its function returns.  The parent process will only exit when all threads have exited.  Note that if a thread calls detach(), there is no way for it to return an exit status.</p>

<blockquote class="code">

<script type='text/javascript'>
<!--

-->
</script>
<font face="monospace">
<font color="#800080">#include&nbsp;</font><font color="#ff00ff">&lt;rudiments/thread.h&gt;</font><br>
<font color="#800080">#include&nbsp;</font><font color="#ff00ff">&lt;rudiments/process.h&gt;</font><br>
<font color="#800080">#include&nbsp;</font><font color="#ff00ff">&lt;rudiments/snooze.h&gt;</font><br>
<font color="#800080">#include&nbsp;</font><font color="#ff00ff">&lt;rudiments/stdio.h&gt;</font><br>
<br>
<font color="#0000ff">// struct for passing arguments into the thread</font><br>
<font color="#2e8b57"><b>struct</b></font>&nbsp;args {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*th;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>int32_t</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>uint16_t</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max;<br>
};<br>
<br>
<font color="#0000ff">// function that will be spawned as a thread</font><br>
<font color="#2e8b57"><b>void</b></font>&nbsp;count(<font color="#2e8b57"><b>void</b></font>&nbsp;*args) {<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>struct</b></font>&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp; *a=(<font color="#2e8b57"><b>struct</b></font>&nbsp;args *)args;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a-&gt;th-&gt;detach();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a"><b>for</b></font>&nbsp;(<font color="#2e8b57"><b>uint16_t</b></font>&nbsp;c=<font color="#ff00ff">0</font>; c&lt;a-&gt;max; c++) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdoutput.printf(<font color="#ff00ff">&quot;&nbsp;&nbsp;</font><font color="#6a5acd">%d</font><font color="#ff00ff">:&nbsp;</font><font color="#6a5acd">%d</font><font color="#6a5acd">\n</font><font color="#ff00ff">&quot;</font>,a-&gt;id,c);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
}<br>
<br>
<font color="#2e8b57"><b>int</b></font>&nbsp;main(<font color="#2e8b57"><b>int</b></font>&nbsp;argc,&nbsp;<font color="#2e8b57"><b>const</b></font>&nbsp;<font color="#2e8b57"><b>char</b></font>&nbsp;**argv) {<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// do we even support threads?</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#a52a2a"><b>if</b></font>&nbsp;(!thread::supportsThreads()) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdoutput.printf(<font color="#ff00ff">&quot;thread are not supported</font><font color="#6a5acd">\n</font><font color="#ff00ff">&quot;</font>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process::exit(<font color="#ff00ff">1</font>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// create the threads</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;&nbsp;t1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;&nbsp;t2;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// define arguments to pass to each thread</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>struct</b></font>&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp; a1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a1.th=&amp;t1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a1.id=<font color="#ff00ff">1</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a1.max=<font color="#ff00ff">100</font>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#2e8b57"><b>struct</b></font>&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp; a2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a2.th=&amp;t2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a2.id=<font color="#ff00ff">2</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a2.max=<font color="#ff00ff">200</font>;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// spawn the threads</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.spawn((<font color="#2e8b57"><b>void</b></font>&nbsp;*(*)(<font color="#2e8b57"><b>void</b></font>&nbsp;*))count,(<font color="#2e8b57"><b>void</b></font>&nbsp;*)&amp;a1,<font color="#ff00ff">true</font>);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2.spawn((<font color="#2e8b57"><b>void</b></font>&nbsp;*(*)(<font color="#2e8b57"><b>void</b></font>&nbsp;*))count,(<font color="#2e8b57"><b>void</b></font>&nbsp;*)&amp;a2,<font color="#ff00ff">true</font>);<br>
}<br>
</font>
<!-- vim: set foldmethod=manual : -->
</blockquote>

</body>
</html>
